<?php
declare (strict_types = 1);

namespace app\command;

use think\console\Command;
use think\console\Input;
use think\console\input\Argument;
use think\console\input\Option;
use think\console\Output;
use PhpOffice\PhpWord\IOFactory;
use PhpOffice\PhpWord\PhpWord;
use think\exception\FileException;
use think\Image;
use app\common\tools\ImageHandle;

class HandleWordImg extends Command
{
    private $count = 2;
    const WIDTH = 450;
    const HEIGHT = 300;
    const FONT_PATH = 'simhei.ttf';
    const FONT_SIZE = 10;
    const SOURCE_PNG = '/source_png/';
    const COMPLETE_PNG = '/complete_png/';
    const OPTION = [
        "A.A",
        "B.B",
        "C.C",
        "D.D",
        "E.E",
//        '<textbreak>',
    ];
    const OPTION_FILE = [
        "docx"
    ];
    protected function configure()
    {
        // 指令配置
        $this->setName('app\command\handleWordImg')
            ->setDescription('word文档图片合成');
    }

    protected function execute(Input $input, Output $output)
    {
        self::handleWordList();
//        self::delImgDir();

    }

    public static function delImgDir()
    {
        $fileList = self::getFileList(self::getPath());

        foreach ($fileList as $val) {
            if (is_dir($val) && stristr($val, '图片路径')) {
                echo sprintf("----图片路径删除--结束-------{$val}------------\n");
                self::delDirTree($val);
            }
        }
    }

    public static function handleWordList()
    {
        // 获取目录下所有文件
        $fileList = self::getFileList(self::getPath());

        $wordfileList = self::getWordFileList($fileList);

        var_dump(count($wordfileList));die;

        foreach ($wordfileList as $val) {
            echo sprintf("------开始-------{$val->getPathname()}------------\n");
            self::handleWord($val);
            echo sprintf("------结束-------{$val->getPathname()}------------\n");
        }

    }

    public static function getWordFileList($data)
    {
        $list = [];
        foreach ($data as $val) {
            if (is_dir($val)) continue;
            $file = self::open($val);
//            if (stristr($file->getFilename(), '已完成-')) continue;
//            if (stristr($file->getFilename(), '--删除--')) continue;
            if (in_array($file->getExtension(), self::OPTION_FILE)) {
                array_push($list, $file);
            }
        }

        return $list;
    }

    public static function delNullFileList($data)
    {
        $list = [];
        foreach ($data as $val) {
            if (is_dir($val)) continue;
            $file = self::open($val);
            if (stristr($file->getFilename(), '已完成-')) continue;
            if (stristr($file->getFilename(), '--删除--')) {
                array_push($list, $file);
            }
        }

        foreach ($list as $val) {
            unlink($val->getPathname());
        }
        return $list;
    }

    public static function getFileList($dir)
    {
        $dir_array = [];
        // 读取当前目录下的所有文件和目录（不包含子目录下文件）
        $files = scandir($dir);

        if (is_array($files)) {
            foreach ($files as $val) {
                // 跳过. 和 ..
                if ($val == '.' || $val == '..')
                    continue;

                // 判断是否是目录
                $pathName = $dir . $val;
                if (is_dir($pathName)) {
                    // 将当前目录添加进数组
                    $pathName = $pathName . '/';
                    $dir_array[] = $pathName;
                    // 递归继续往下寻找
                    $dir_array_res = self::getFileList($pathName);
                    $dir_array = array_merge($dir_array, $dir_array_res);
                } else {
                    // 不是目录也需要将当前文件添加进数组
                    $dir_array[] = $pathName;
                }
            }
        }

        return $dir_array;

    }

    public static function handleWord(\SplFileInfo $file)
    {
        $fileName = $file->getPathname();
        $word = self::getWord($fileName);
//        foreach ($word as $val) {
//            if (stristr($val, '<gifdata>')) {
//                echo sprintf("-----处理失败--------%s--------------------\n", $fileName);
//                echo sprintf("-----失败原因--------无法识别 image/gif--------------------\n");
//                return;
//            };
//        }

        $handleDataList = self::getHandleDataList($word);

        foreach ($handleDataList as $val) {
            $pngDataItem = self::formatPngData($val);
            if (stristr($val['title'], '<imgdata>')) {
                echo sprintf("---%s-----------题干是图片--------------------\n", $fileName);
            }

//            if (stristr($val['title'], '/')) {
//                echo sprintf("-----处理失败--------%s--------------------\n", $fileName);
//                echo sprintf("-----失败原因--------题干有斜杠/--------------------\n");
//                self::delDir($pngDataItem['dir']);
//                return;
//            }


            $completeItem = self::mergePngFile($pngDataItem);
            $valKey = $val['key'];
            $firstKey = array_shift($valKey);
            $secondKey = array_shift($valKey);

            $word[$firstKey] = $val['title'];
            $word[$secondKey] = '<imgdatabig>'. $completeItem['img_data'].'<imgdatabig>';

            foreach ($valKey as $value) {
                unset($word[$value]);
            }
        }

        $wordDataCompleted = array_values($word);
        self::createWord($wordDataCompleted, $file->getPath() . '/已完成-' . $file->getFilename());
        unlink($fileName);
    }

    public static function createWord($data, $savePath){
        $phpWord = new PhpWord();
        $section = $phpWord->addSection();
        foreach ($data as $val) {
            if (stristr($val, '<imgdatabig>')) {
                $imgItemArr = explode('<imgdatabig>', $val);
                $img = $imgItemArr[1];
                //$imageData = 'data:image/png;base64,' . $img;
                //$imgText = '<img src="'.$imageData.'">';
                $section->addImage(base64_decode($img), ['width'=>self::WIDTH, 'height'=>self::HEIGHT]);
                continue;
            }

            if (stristr($val, '<imgdata>')) {
                $imgItemArr = explode('<imgdata>', $val);
                $img = $imgItemArr[1];
                //$imageData = 'data:image/png;base64,' . $img;
                //$imgText = '<img src="'.$imageData.'">';
                $section->addImage(base64_decode($img));
                continue;
            }

            if (stristr($val, '<gifdata>')) {
                $imgItemArr = explode('<gifdata>', $val);
                $img = $imgItemArr[0];
                //$imageData = 'data:image/png;base64,' . $img;
                //$imgText = '<img src="'.$imageData.'">';
//                $section->addImage(base64_decode($img));
                $section->addText($img);
                continue;
            }

            if (stristr($val, '<textbreak>')) {
                $section->addTextBreak(1);
                continue;
            }

            $section->addText($val);
        }

        $objWriter = IOFactory::createWriter($phpWord, 'Word2007');
        $objWriter->save($savePath);
    }

    public static function getHandleDataList($word)
    {
        $list = [];
        $listItem = [];
        foreach ($word as $key => $val) {
            if (in_array($val, self::OPTION)) {
                array_push($listItem, $key);
            } else {
                if (count($listItem) > 1) {
                    array_push($list, $listItem);
                    $listItem = [];
                }
            }
        }


        // 封装需要处理图片的数据
        $handleDataList = [];
        foreach ($list as $key => $val) {
            $handlekeyItem = [];
            $handleDataItem = [];
            $handleObjItem = [];

            $item = $val;
            $range = count($item)+2;
            while ($range > 0) {
                array_push($handlekeyItem, $item[0]-$range);
                $range--;
            }

            foreach ($handlekeyItem as $value) {
                array_push($handleDataItem, $word[$value]);
            }

            $titleOld = $handleDataItem[0];
            $title = explode('.', $titleOld);
            if (empty($title[1])) {
                $handleDataItem[0] = '  ';
            } else {
                $handleDataItem[0] = $title[1];
            }

            $handleObjItem['key'] = $handlekeyItem;
            $handleObjItem['data'] = $handleDataItem;
            $handleObjItem['title'] = $title[0].'.';

            array_push($handleDataList, $handleObjItem);
        }

        return $handleDataList;

    }

    /**
     * 合并图片操作
     * @param $data
     * @return mixed
     */
    public static function mergePngFile($data)
    {
        $fontPath = root_path() . self::FONT_PATH;
        $imageMain = ImageHandle::create(
            $data['white_path'],
            $data['width'],
            $data['height']
        );

        $image = ImageHandle::open($imageMain->getPathname());
        $content = $data['content'];

        $height = 0;
        $width = $data['width'] / 4;
        foreach ($content as $key => $val) {
            $height += $val['height'];

            if (empty($val['title'])) continue;
            if (stristr($val['title'], '<textbreak>')) continue;
            // if (stristr($val['title'], '<imgdata>')) continue;

            if ($val['type'] == 'text') {
                $image->text($val['title'], $fontPath, self::FONT_SIZE, '#000000', ImageHandle::WATER_NORTHWEST);
            }

            if ($val['type'] == 'png') {
                // $image->water($val['path'], [$width, $height]);
                $image->text($val['title'], $fontPath, self::FONT_SIZE, '#000000', [$width - 40, $height]);
            }
        }

        $height = 0;
        $width = $data['width'] / 4;
        foreach ($content as $key => $val) {
            $height += $val['height'];
            if ($val['type'] == 'png') {
                $image->water($val['path'], [$width, $height]);
            }
        }

        $image->save($data['path']);
        $imageData = file_get_contents($data['path']);
        $data['img_data'] = base64_encode($imageData);

        self::delDir($data['dir']);
//        var_dump($data['dir']);

        return $data;
    }

    /**
     * 图片下载
     * @param $data
     * @return mixed
     */
    public static function formatPngData($data)
    {
        $imgDir = self::getPath() . implode("-", $data['key']);
        $dir = $imgDir . self::SOURCE_PNG;
        $completeDir = $imgDir . self::COMPLETE_PNG;

        $optionList = $data['data'];
        $imgContentList = [];
        foreach ($optionList as $key => $val) {
            $imgContentItem = [];
            if (stristr($val, '<imgdata>')) {
                $imgItemArr = explode('<imgdata>', $val);
                if (!is_dir($dir)) {
                    mkdir($dir,0777,true);
                }
                $imgTitle = $imgItemArr[0];
                $imgPath = $dir . $imgTitle . '-.png';
                $img = $imgItemArr[1];
                file_put_contents($imgPath, base64_decode($img));

                $image = ImageHandle::open($imgPath);
                // 返回图片的宽度
                $width = $image->width();
                // 返回图片的高度
                $height = $image->height();

                $imgContentItem['title'] = $imgTitle;
                $imgContentItem['img_data'] = $img;
                $imgContentItem['width'] = $width;
                $imgContentItem['height'] = $height;
                $imgContentItem['path'] = $imgPath;
                $imgContentItem['type'] = 'png';
            } else {
                $width = 20*30;
                $height = ceil(strlen($val)/90);
                $imgContentItem['title'] = $val;
                $imgContentItem['img_data'] = '';
                $imgContentItem['width'] = $width;
                $imgContentItem['height'] = $height;
                $imgContentItem['path'] = '';
                $imgContentItem['type'] = 'text';
            }
            array_push($imgContentList, $imgContentItem);
        }

        // $widthArray = array_column($imgContentList, 'width');
        $heightArray = array_column($imgContentList, 'height');

        $widthMain = self::WIDTH;
        $heightMain = array_sum($heightArray) + count($heightArray) * 20;

        if (!is_dir($completeDir)) {
            mkdir($completeDir,0777,true);
        }

        $md5Title = md5($data['title']);
        $data['white_path'] = $completeDir . $md5Title . 'white.-.png';
        $data['path'] = $completeDir . $md5Title . '-.png';
        $data['dir'] = $imgDir;
        $data['width'] = $widthMain;
        $data['height'] = $heightMain;
        $data['content'] = $imgContentList;
        return $data;
    }

    /**
     * 获取word文档内容
     * @param string $path
     * @return array
     */
    public static function getWord($path = '')
    {
        //加载word文档，使用phpword处理
        $phpWord = \PhpOffice\PhpWord\IOFactory::load($path);
        return self::getNodeContent($phpWord);
    }

    /**
     * 根据word主节点获取分节点内容
     * @param $word
     * @return array
     */
    public static function getNodeContent($word)
    {
        $return = [];
        //分解部分
        foreach ($word->getSections() as $section)
        {
            if ($section instanceof \PhpOffice\PhpWord\Element\Section) {
                //分解元素
                foreach ($section->getElements() as $element)
                {
                    //文本元素
                    if ($element instanceof \PhpOffice\PhpWord\Element\TextRun) {
                        $text = '';
                        foreach ($element->getElements() as $ele) {
                            $text .= self::getTextNode($ele);
                        }
                        $return[] = $text;
                    }
                    //表格元素
                    else if ($element instanceof \PhpOffice\PhpWord\Element\Table) {
                        foreach ($element->getRows() as $ele)
                        {
                            $return[] = self::getTableNode($ele);
                        }
                    }

                    else if ($element instanceof \PhpOffice\PhpWord\Element\TextBreak) {
//                        foreach ($element->getRows() as $ele)
//                        {
//                            $return[] = self::getTableNode($ele);
//                        }
                        $return[] = self::textBreak2text();
                    }
                }
            }
        }
        return $return;
    }

    /**
     * 获取文档节点内容
     * @param $node
     * @return string
     */
    public static function getTextNode($node)
    {
        $return = '';
        //处理文本
        if ($node instanceof \PhpOffice\PhpWord\Element\Text)
        {
            $return .= $node->getText();
        }
        //处理图片
        else if ($node instanceof \PhpOffice\PhpWord\Element\Image)
        {
            $return .= self::pic2text($node);
        }
        //处理文本元素
        else if ($node instanceof \PhpOffice\PhpWord\Element\TextRun) {
            foreach ($node->getElements() as $ele) {
                $return .= self::getTextNode($ele);
            }
        }
        return $return;
    }

    /**
     * 获取表格节点内容
     * @param $node
     * @return string
     */
    public static function getTableNode($node)
    {
        $return = '';
        //处理行
        if ($node instanceof \PhpOffice\PhpWord\Element\Row) {
            foreach ($node->getCells() as $ele)
            {
                $return .= self::getTableNode($ele);
            }
        }
        //处理列
        else if ($node instanceof \PhpOffice\PhpWord\Element\Cell) {
            foreach ($node->getElements() as $ele)
            {
                $return .= self::getTextNode($ele);
            }
        }
        return $return;
    }

    /**
     * 处理word文档中base64格式图片
     * @param $node
     * @return string
     */
    public static function pic2textOld($node)
    {
        //获取图片编码
        $imageData = $node->getImageStringData(true);
        //添加图片html显示标头
        $imageData = 'data:' . $node->getImageType() . ';base64,' . $imageData;
        $return = '<img src="'.$imageData.'">';
        return $return;
    }

    public static function pic2text($node)
    {

        //获取图片编码
        $imageData = $node->getImageStringData(true);
        if ($node->getImageType() == 'image/gif') {
//            var_dump($node->getImageType(), $imageData);
            $return = '<gifdata>'.$imageData.'<gifdata>';
            return $return;
        }

        //添加图片html显示标头
//        $imageData = 'data:' . $node->getImageType() . ';base64,' . $imageData;
        $return = '<imgdata>'.$imageData.'<imgdata>';
        return $return;
    }


    public static function textBreak2text()
    {
        //获取图片编码
//        $imageData = $node->getImageStringData(true);
        //添加图片html显示标头
//        $imageData = 'data:' . $node->getImageType() . ';base64,' . $imageData;
        $return = '<textbreak><textbreak>';
        return $return;
    }

    /**
     * 处理word文档中base64格式图片
     * @param $node
     * @return string
     */
    public static function pic2file($node)
    {
        //图片地址(一般为word文档地址+在word中的锚点位置)
        $imageSrc  = 'images/' . md5($node->getSource()) . '.' . $node->getImageExtension();
        $imageData = $node->getImageStringData(true);
        //将图片保存在本地
        file_put_contents($imageSrc, base64_decode($imageData));
        return $imageSrc;
    }

    /**
     * 将word转化为html(转换存储html文件后展示)
     * @param $path
     * @throws \PhpOffice\PhpWord\Exception\Exception
     */
    public static function word2html($path)
    {
        $phpWord = FileImportService::getOne($path);
        //转为html处理
        $xmlWriter  = IOFactory::createWriter($phpWord, "HTML");
        $path = pathinfo($path);
        $fileName = $path['dirname'] . '/' . $path['filename'] . '.html';
        $xmlWriter->save($fileName);
        $html = file_get_contents($fileName);
        echo $html;
        die;

    }

    public static function open($file)
    {
        if (is_string($file)) {
            $file = new \SplFileInfo($file);
        }
        if (!$file->isFile()) {
            throw new FileException('文件不存在');
        }
        return $file;
    }

    protected static function delDir($dir)
    {
        if(strtoupper(substr(PHP_OS, 0, 3)) == 'WIN') {
            // $str = "rmdir /s/q " . $dir;
            self::delDirTree($dir);
        }

        $str = "rm -Rf " . $dir;
        exec($str);
    }

    protected static function delDirTree($dir)
    {
        $filelist = self::getFileList($dir);
        foreach ($filelist as $value) {
            if(is_dir($value)) continue;
            unlink($value);
        }

        foreach ($filelist as $value) {
            if(!is_dir($value)) continue;
            rmdir($value);
        }

        rmdir($dir);
    }

    protected static function copyFile(\SplFileInfo $file, $type)
    {
        $dstdir = self::getPath() . 'problem';
        if ($type == 'gif') {
            $dstdir = self::getPath() . 'gif';
        }
        if (is_dir($dstdir)) {
            mkdir($dstdir,0777,true);
        }
        copy($file->getPathname(), $dstdir);
    }

    protected static function getPath()
    {
        return root_path().'public/static/';
    }
}
